﻿#include "libraryfactory.h"
#include <QLibrary>
#include <QMap>
#include <QMutex>
#include <QDebug>
#include <QDir>
// 初始化静态成员变量
QMap<QString, QLibrary *> LibraryFactory::s_libraries;
QMutex LibraryFactory::s_mutex;

void *LibraryFactory::resolve(const QString &dllName)
{
    QMutexLocker locker(&s_mutex);
    QLibrary *library = nullptr;
    const char *symbolName = "instance"; // 硬编码约定的函数名

    // 检查库是否已被加载和缓存
    if (s_libraries.contains(dllName)) {
        library = s_libraries.value(dllName);
    } else {
        //如果未缓存，则加载新库
        library = new QLibrary(dllName);
        library->setLoadHints(QLibrary::ResolveAllSymbolsHint);

        if (!library->load()) {
            qWarning() << "LibraryFactory: Failed to load library" << dllName
                       << "Error:" << library->errorString();
            delete library;
            return nullptr;
        }
        s_libraries.insert(dllName, library);
    }

    //  从库中解析 "instance" 符号
    void *func_ptr_raw = reinterpret_cast<void *>(library->resolve(symbolName));

    if (!func_ptr_raw) {
        qWarning() << "LibraryFactory: Failed to resolve symbol '" << symbolName
                   << "' in library '" << dllName << "'. Error:" << library->errorString();
        return nullptr;
    }

    //  将解析出的符号指针转换为正确的函数指针类型并调用
    // 定义与 "extern "C" void* instance()" 匹配的函数指针类型
    using InstanceFunc = void *(*)();

    // 进行转换
    InstanceFunc create_instance_func = reinterpret_cast<InstanceFunc>(func_ptr_raw);

    // 调用函数以创建设备实例
    void *device_instance = create_instance_func();

    // 检查实例是否成功创建
    if (!device_instance) {
        qWarning() << "LibraryFactory: 'instance' function in" << dllName << "returned a nullptr. Object creation failed inside the library.";
        return nullptr;
    }

    //   返回创建出的设备实例指针
    return device_instance;
}

void LibraryFactory::cleanup()
{
    QMutexLocker locker(&s_mutex);
    if (s_libraries.isEmpty()) {
        return;
    }
    //    qDebug() << "LibraryFactory: Cleaning up" << s_libraries.count() << "cached libraries.";

    for (QLibrary *library : qAsConst(s_libraries)) {
        if (library->isLoaded()) {
            library->unload();
        }
        delete library;
    }
    s_libraries.clear();
}
